package com.qingzhou.web.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.*;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.fastjson2.JSONObject;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.solon.service.impl.ServiceImpl;
import com.qingzhou.common.utils.FileUtil;
import com.qingzhou.common.web.domain.FileVo;
import com.qingzhou.framework.config.FileConfig;
import com.qingzhou.web.repository.dao.CollectDao;
import com.qingzhou.web.repository.dao.PatientDao;
import com.qingzhou.web.repository.entity.*;
import com.qingzhou.web.repository.mapper.PatientMapper;
import com.qingzhou.web.service.*;
import com.qingzhou.web.service.impl.convert.DistrictConverter;
import com.qingzhou.web.service.impl.params.request.*;
import com.qingzhou.web.service.impl.params.vo.PatientVo;
import com.qingzhou.web.service.impl.params.vo.excel.*;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.noear.solon.annotation.Bean;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.handle.UploadedFile;
import org.noear.solon.data.annotation.Tran;

import javax.mail.FetchProfile;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Component
@Slf4j
public class PatientServiceImpl extends ServiceImpl<PatientMapper, PatientEntity> implements PatientService {

    @Inject
    PatientDao patientDao;
    @Inject
    DataCheckLogService dataCheckLogService;
    @Inject
    CollectDao collectDao;

    @Inject
    CollectService collectService;
    @Inject
    OmicsCollectService omicsCollectService;
    @Inject
    CheckRecordsService checkRecordsService;
    @Inject
    TreatmentService treatmentService;
    @Inject
    PathologyService pathologyService;
    @Inject
    ImagingService imagingService;
    @Inject
    VisitService visitService;
    @Inject
    SurgeryService surgeryService;
    @Inject
    OmicsService omicsService;
    @Inject
    FileConfig fileConfig;
    @Inject
    HospitalDistrictService hospitalDistrictService;

    @Override
    public int add(PatientAddForm form) {
        Assert.isTrue(StrUtil.isNotEmpty(form.getPatientCode()), "患者编号不允许为空");
        PatientEntity exists = patientDao.getMapper().selectOneByQuery(QueryWrapper.create().select("patient_code").eq("patient_code", form.getPatientCode()));
        Assert.isTrue(ObjUtil.isNull(exists), "患者编号已存在");

        PatientEntity entity = BeanUtil.copyProperties(form, PatientEntity.class);
        entity.setStatus("create");
        entity.setIsSupplemented("N");
        return patientDao.add(entity);
    }

    @Override
    public int delete(PatientDeleteForm form) {
        PatientEntity entity = this.getByIdMustExists(form.getId());
        Assert.isTrue(StrUtil.equalsIgnoreCase("create", entity.getStatus()), "该状态不允许删除");

        String patientCode = entity.getPatientCode();
        long row = 0;
        // 手术情况
        row += surgeryService.getMapper().selectCountByQuery(QueryWrapper.create().eq(SurgeryEntity::getPatientCode, patientCode));
        // 随访信息
        row += visitService.getMapper().selectCountByQuery(QueryWrapper.create().eq(VisitEntity::getPatientCode, patientCode));
        // 治疗信息
        row += treatmentService.getMapper().selectCountByQuery(QueryWrapper.create().eq(TreatmentEntity::getPatientCode, patientCode));
        // ctDNA-MRD检测
        row += collectService.getMapper().selectCountByQuery(QueryWrapper.create().eq(CollectEntity::getPatientCode, patientCode));
        // 组学采样信息
        row += omicsCollectService.getMapper().selectCountByQuery(QueryWrapper.create().eq(OmicsCollectEntity::getPatientCode, patientCode));
        // 病理信息
        row += pathologyService.getMapper().selectCountByQuery(QueryWrapper.create().eq(PathologyEntity::getPatientCode, patientCode));
        // 影像检测
        row += imagingService.getMapper().selectCountByQuery(QueryWrapper.create().eq(ImagingEntity::getPatientCode, patientCode));
        // 组学分析
        row += omicsService.getMapper().selectCountByQuery(QueryWrapper.create().eq(OmicsEntity::getPatientCode, patientCode));
        Assert.isTrue(row==0, "已填写数据，无法删除，请联系管理员协助。");

        return patientDao.delete(form.getId());
    }

    @Override
    public Page<PatientEntity> page(Page<PatientEntity> page, PatientEntity entity) {
        QueryWrapper queryWrapper = buildSearchCondition(entity);
        queryWrapper.orderBy("create_time desc");
        Page<PatientEntity> paginate = patientDao.getMapper().paginate(page, queryWrapper);

        // 转义
        List<PatientEntity> records = paginate.getRecords();
        List<String> codeList = records.stream().map(PatientEntity::getDistrictCode).collect(Collectors.toList());
        List<HospitalDistrictEntity> districtCodeList = hospitalDistrictService.list(QueryWrapper.create().in("district_code", codeList));
        Map<String, String> codeMap = districtCodeList.stream().collect(Collectors.toMap(HospitalDistrictEntity::getDistrictCode, HospitalDistrictEntity::getDistrictName));
        records.forEach(item->{
            item.setDistrictCode(codeMap.get(item.getDistrictCode()));
        });
        return paginate;
    }

    private QueryWrapper buildSearchCondition(PatientEntity entity) {
        if (ObjUtil.isNull(entity)) return QueryWrapper.create();
        String patientName = entity.getPatientName();
        String patientCode = entity.getPatientCode();
        String beHospitalNum = entity.getBeHospitalNum();
        String testItem = entity.getTestItem();
        String hospitalSite = entity.getHospitalSite();
        String districtCode = entity.getDistrictCode();
        String belongingGroup = entity.getBelongingGroup();
        QueryWrapper queryWrapper = QueryWrapper.create();
        if (StrUtil.isNotEmpty(patientName)) {
            List<String> sql = new ArrayList<>();
            List<String> split = StrUtil.split(patientName.trim(), "\n");
            split.forEach(item -> {
                if (StrUtil.isNotEmpty(item)) {
                    sql.add("patient_name like '%" + item.trim() + "%'");
                }
            });
            queryWrapper.and(CollUtil.join(sql, " or "));
        }
        if (StrUtil.isNotEmpty(patientCode)) {
            List<String> sql = new ArrayList<>();
            List<String> split = StrUtil.split(patientCode.trim(), "\n");
            split.forEach(item -> {
                if (StrUtil.isNotEmpty(item)) {
                    sql.add("patient_code like '%" + item.trim() + "%'");
                }
            });
            queryWrapper.and(CollUtil.join(sql, " or "));
        }
        if (StrUtil.isNotEmpty(beHospitalNum)) {
            queryWrapper.like("be_hospital_num", beHospitalNum);
        }
        if (StrUtil.isNotEmpty(testItem)) {
            queryWrapper.like("test_item", testItem);
        }
        if (StrUtil.isNotEmpty(hospitalSite)) {
            queryWrapper.eq("hospital_site", hospitalSite);
        }
        if (StrUtil.isNotEmpty(districtCode)) {
            queryWrapper.eq("district_code", districtCode);
        }
        if(StrUtil.isNotEmpty(belongingGroup)){
            if(StrUtil.equals("other",belongingGroup)){
                queryWrapper.and("belonging_group is null or belonging_group = '' ");
            }else{
                queryWrapper.eq("belonging_group",belongingGroup);
            }
        }
        return queryWrapper;
    }

    @Override
    public PatientVo detail(PatientDetailForm form) {
        PatientEntity entity = this.getByIdMustExists(form.getId());
        PatientVo patientVo = BeanUtil.copyProperties(entity, PatientVo.class);
        patientVo.setDistrictName(DistrictConverter.getConvertString(entity.getDistrictCode()));
        return patientVo;
    }

    @Override
    public int edit(PatientEditForm form) {
        PatientEntity entity = this.getByIdMustExists(form.getId());
        Assert.isTrue(StrUtil.equalsIgnoreCase("create", entity.getStatus()), "该状态不允许编辑");

        BeanUtil.copyProperties(form, entity,"patientCode"); //患者编号不能变
        return patientDao.update(entity);
    }

    @Override
    public int supplement(PatientEditForm form) {
        PatientEntity entity = this.getByIdMustExists(form.getId());
        Assert.isTrue(StrUtil.equalsIgnoreCase("create", entity.getStatus()), "该状态不允许编辑");

        BeanUtil.copyProperties(form, entity,"patientCode"); //患者编号不能变
        entity.setIsSupplemented("Y");
        return patientDao.update(entity);
    }

    @Override
    public int forceEdit(PatientForceEditForm form) {
        PatientEntity entity = this.getByIdMustExists(form.getId());
        Assert.isTrue(StrUtil.equalsIgnoreCase("done", entity.getStatus()), "该状态不允许数据检查");

        JSONObject diffContent = DataCheckLogServiceImpl.diff(entity, form, new String[]{"visitRemindDate"});
        BeanUtil.copyProperties(form, entity,"patientCode"); //患者编号不能变
        int rows = patientDao.update(entity);

        if (rows > 0 && MapUtil.isNotEmpty(diffContent)) {
            DataCheckLogAddForm addForm = new DataCheckLogAddForm(EdcConstants.EDC_PATIENT, diffContent, entity.getPatientCode());
            dataCheckLogService.add(addForm);
        }
        return rows;
    }

    @Override
    public int done(PatientDoneForm form) {
        PatientEntity entity = this.getByIdMustExists(form.getId());
        Assert.isTrue(StrUtil.equalsIgnoreCase("create", entity.getStatus()), "该状态不允许核实");

        BeanUtil.copyProperties(form, entity,"patientCode"); //患者编号不能变
        entity.setStatus("done");
        return patientDao.update(entity);
    }

    @Override
    public int stop(PatientStopForm form) {
        PatientEntity entity = patientDao.getById(form.getId());
        Assert.isTrue(ObjUtil.isNotNull(entity), "数据不见了");
        Assert.isTrue(!StrUtil.equalsIgnoreCase("stop", entity.getStatus()), "该状态不允许终止");

        entity.setStatus("stop");
        entity.setStopReason(form.getStopReason());
        return patientDao.update(entity);
    }

    @SneakyThrows
    @Override
    public void export(PatientExportForm form) {
        ExcelWriter excelWriter = EasyExcel.write(Context.current().outputStream())
                .registerWriteHandler(new CustomCellWriteWidthConfig())
                .registerWriteHandler(this.buildExcelStyle())
                .excelType(ExcelTypeEnum.XLS)
                .build();

        QueryWrapper condition = QueryWrapper.create();
        if (ObjUtil.isNotNull(form)) {
            if (StrUtil.isNotEmpty(form.getIds())) {
                List<String> idsList = StrUtil.split(form.getIds(), ",");
                condition = condition.in("id", idsList).orderBy("id");
            } else {
                QueryWrapper queryWrapper = buildSearchCondition(form);
                condition = queryWrapper.orderBy("create_time desc,patient_code desc");
            }
        }

        List<PatientEntity> patientList = this.list(condition);
        if (CollUtil.isEmpty(patientList)) {
            throw new RuntimeException("暂无数据");
        }

        int sheetNum = 0;
        // 按patientCode分组
        List<String> patientCodeList = patientList.stream().map(PatientEntity::getPatientCode).collect(Collectors.toList());
        Map<String, PatientEntity> patientMap = patientList.stream().collect(Collectors.toMap(PatientEntity::getPatientCode, v -> v));
        List<PatientExcelVo> patientVoList = patientList.stream().map(item -> BeanUtil.copyProperties(item, PatientExcelVo.class)).collect(Collectors.toList());
        WriteSheet patientSheet = EasyExcel.writerSheet(sheetNum++, EdcConstants.EDC_PATIENT).head(PatientExcelVo.class).build();
        excelWriter.write(patientVoList, patientSheet);

        List<SurgeryEntity> surgeryList = surgeryService.list(QueryWrapper.create().in("patient_code", patientCodeList).orderBy("create_time desc,patient_code desc"));
        List<SurgeryExcelVo> surgeryVoList = surgeryList.stream().map(item -> BeanUtil.copyProperties(item, SurgeryExcelVo.class)).collect(Collectors.toList());
        fillData(patientMap, surgeryVoList);
        WriteSheet surgerySheet = EasyExcel.writerSheet(sheetNum++, EdcConstants.EDC_SURGERY).head(SurgeryExcelVo.class).build();
        excelWriter.write(surgeryVoList, surgerySheet);

        List<VisitEntity> visitList = visitService.list(QueryWrapper.create().in("patient_code", patientCodeList).orderBy("create_time desc,patient_code desc"));
        List<VisitExcelVo> visitVoList = visitList.stream().map(item -> BeanUtil.copyProperties(item, VisitExcelVo.class)).collect(Collectors.toList());
        fillData(patientMap, visitVoList);
        WriteSheet visitSheet = EasyExcel.writerSheet(sheetNum++, EdcConstants.EDC_VISIT).head(VisitExcelVo.class).build();
        excelWriter.write(visitVoList, visitSheet);

        List<TreatmentEntity> treatmentList = treatmentService.list(QueryWrapper.create().in("patient_code", patientCodeList).orderBy("create_time desc,patient_code desc"));
        List<TreatmentExcelVo> treatmentVoList = treatmentList.stream().map(item -> BeanUtil.copyProperties(item, TreatmentExcelVo.class)).collect(Collectors.toList());
        fillData(patientMap, treatmentVoList);
        WriteSheet treatmentSheet = EasyExcel.writerSheet(sheetNum++, EdcConstants.EDC_TREATMENT).head(TreatmentExcelVo.class).build();
        excelWriter.write(treatmentVoList, treatmentSheet);

        List<CollectEntity> collectList = collectService.list(QueryWrapper.create().in("patient_code", patientCodeList).orderBy("create_time desc,patient_code desc"));
        List<CollectExcelVo> collectVoList = collectList.stream().map(item -> BeanUtil.copyProperties(item, CollectExcelVo.class)).collect(Collectors.toList());
        fillData(patientMap, collectVoList);
        WriteSheet collectSheet = EasyExcel.writerSheet(sheetNum++, EdcConstants.EDC_COLLECT).head(CollectExcelVo.class).build();
        excelWriter.write(collectVoList, collectSheet);

        List<OmicsCollectEntity> omicsCollectList = omicsCollectService.list(QueryWrapper.create().in("patient_code", patientCodeList).orderBy("create_time desc,patient_code desc"));
        List<OmicsCollectExcelVo> omicsCollectVoList = omicsCollectList.stream().map(item -> BeanUtil.copyProperties(item, OmicsCollectExcelVo.class)).collect(Collectors.toList());
        fillData(patientMap, omicsCollectVoList);
        WriteSheet omicsCollectSheet = EasyExcel.writerSheet(sheetNum++, EdcConstants.EDC_OMICS_COLLECT).head(OmicsCollectExcelVo.class).build();
        excelWriter.write(omicsCollectVoList, omicsCollectSheet);

        /*List<CheckRecordsEntity> crList = checkRecordsService.list(QueryWrapper.create().in("patient_code", patientCodeList).orderBy("create_time desc,patient_code desc"));
        List<CheckRecordsExcelVo> crVoList = crList.stream().map(item -> BeanUtil.copyProperties(item, CheckRecordsExcelVo.class)).collect(Collectors.toList());
        fillData(patientMap, crVoList);
        WriteSheet crSheet = EasyExcel.writerSheet(6, "检测结果").head(CheckRecordsExcelVo.class).build();
        excelWriter.write(crVoList, crSheet);*/

        List<PathologyEntity> pathologyList = pathologyService.list(QueryWrapper.create().in("patient_code", patientCodeList).orderBy("create_time desc,patient_code desc"));
        List<PathologyExcelVo> pathologyVoList = pathologyList.stream().map(item -> BeanUtil.copyProperties(item, PathologyExcelVo.class)).collect(Collectors.toList());
        fillData(patientMap, pathologyVoList);
        WriteSheet pathologySheet = EasyExcel.writerSheet(sheetNum++, EdcConstants.EDC_PATHOLOGY).head(PathologyExcelVo.class).build();
        excelWriter.write(pathologyVoList, pathologySheet);

        List<ImagingEntity> imagingList = imagingService.list(QueryWrapper.create().in("patient_code", patientCodeList).orderBy("create_time desc,patient_code desc"));
        List<ImagingExcelVo> imagingVoList = imagingList.stream().map(item -> BeanUtil.copyProperties(item, ImagingExcelVo.class)).collect(Collectors.toList());
        fillData(patientMap, imagingVoList);
        // 影像学，需要把一行数据根据胸部影像拆成多行
        imagingVoList = this.splitMultiRows(imagingVoList);
        WriteSheet imagingSheet = EasyExcel.writerSheet(sheetNum++, EdcConstants.EDC_IMAGING)
                .head(ImagingExcelVo.class)
                .build();
        excelWriter.write(imagingVoList, imagingSheet);

        List<OmicsEntity> omicsList = omicsService.list(QueryWrapper.create().in("patient_code", patientCodeList).orderBy("create_time desc,patient_code desc"));
        List<OmicsExcelVo> omicsVoList = omicsList.stream().map(item -> BeanUtil.copyProperties(item, OmicsExcelVo.class)).collect(Collectors.toList());
        fillData(patientMap, omicsVoList);
        WriteSheet omicsSheet = EasyExcel.writerSheet(sheetNum++, EdcConstants.EDC_OMICS).head(OmicsExcelVo.class).build();
        excelWriter.write(omicsVoList, omicsSheet);

        excelWriter.close();
    }

    private List<ImagingExcelVo> splitMultiRows(List<ImagingExcelVo> imagingVoList) {
        if(CollUtil.isEmpty(imagingVoList)) return imagingVoList;

        List<ImagingExcelVo> result = new ArrayList<>();

        // imgTestInfoList 下的 imgChestTestInfoList 作为一行
        if(CollUtil.isNotEmpty(imagingVoList)){
            Integer serialNo = 1;
            for(ImagingExcelVo outVo : imagingVoList){
                List<ImgTestInfo> imgTestInfoList = outVo.getImgTestInfoList();
                if(CollUtil.isNotEmpty(imgTestInfoList)){
                    for(ImgTestInfo imgInfo : imgTestInfoList){
                        List<ImgChestTestInfo> infoList = imgInfo.getImgChestTestInfoList();
                        if(CollUtil.isNotEmpty(infoList)){
                            for(ImgChestTestInfo bzInfo : infoList){
                                // 一个病灶为一行
                                ImagingExcelVo item = new ImagingExcelVo();
                                BeanUtil.copyProperties(outVo,item);
                                BeanUtil.copyProperties(imgInfo,item);
                                BeanUtil.copyProperties(bzInfo,item);
                                item.setSerialNo(serialNo);
                                result.add(item);
                            }
                        }else{
                            // 一个影像为一行
                            ImagingExcelVo item = new ImagingExcelVo();
                            BeanUtil.copyProperties(outVo,item);
                            BeanUtil.copyProperties(imgInfo,item);
                            item.setSerialNo(serialNo);
                            result.add(item);
                        }
                    }
                }else{
                    // 一个检测为一行
                    ImagingExcelVo item = new ImagingExcelVo();
                    BeanUtil.copyProperties(outVo,item);
                    item.setSerialNo(serialNo);
                    result.add(item);
                }
                serialNo++;
            }
        }

       /* for(ImagingExcelVo vo : imagingVoList){
            List<ImgTestInfo> infoList = vo.getImgTestInfoList();
            if(CollUtil.isEmpty(infoList) || infoList.size()==1){
                result.add(vo);
            }else{
                int count=0;
                for(ImgTestInfo info : infoList){
                    ImagingExcelVo item = new ImagingExcelVo();
                    if(count==0){
                        BeanUtil.copyProperties(vo,item);
                    }
                    BeanUtil.copyProperties(info,item);
                    result.add(item);
                    count++;
                }
            }
        }*/
        return result;
    }

    @Override
    public String buildPatientCode(String prefix) {
        String patientCode = prefix + RandomUtil.randomNumbers(6);
        long count = this.getMapper().selectCountByQuery(QueryWrapper.create().eq("patient_code", patientCode));
        if (count >= 1) {
            return this.buildPatientCode(prefix);
        } else {
            return patientCode;
        }
    }

    @SneakyThrows
    @Override
    @Tran
    public void uploadFile(PatientUploadFileForm form) {
        PatientEntity entity = this.getByIdMustExists(form.getId());

        List<FileVo> oldFiles = entity.getInformedConsentFile();
        if(StrUtil.equals(form.getType(),"studyCase")){
            oldFiles = entity.getStudyCaseFile();
        }

        List<UploadedFile> added = form.getAddedFileStream();
        boolean uploadNothing = CollUtil.isEmpty(oldFiles)&&CollUtil.isEmpty(added);
        Assert.isTrue(!uploadNothing, "请上传文件");


        // 处理文件流
        if(CollUtil.isNotEmpty(form.getRemovedFileNames())){
            // 先处理删除的
            for (String fileName : form.getRemovedFileNames()){
                oldFiles.removeIf(item -> {
                    boolean equals = StrUtil.equals(item.getName(), fileName);
                    if(equals && cn.hutool.core.io.FileUtil.exist(fileConfig.getSavePath()+item)){
                        cn.hutool.core.io.FileUtil.del(fileConfig.getSavePath()+item);
                    }
                    return equals;
                });
            }
            patientDao.update(entity);
        }

        // 再处理新增的
        List<FileVo> toSave = new ArrayList<>();
        for (UploadedFile file : added) {
            FileVo fileVo = FileUtil.trans(file, fileConfig.getMaxSize(), fileConfig.getFileType(), fileConfig.getSavePath());
            toSave.add(fileVo);
        }
        if(StrUtil.equals(form.getType(),"studyCase")){
            if(entity.getStudyCaseFile()==null){
                entity.setStudyCaseFile(new ArrayList<>());
            }
            entity.getStudyCaseFile().addAll(toSave);
        }else{
            if(entity.getInformedConsentFile()==null){
                entity.setInformedConsentFile(new ArrayList<>());
            }
            entity.getInformedConsentFile().addAll(toSave);
        }

        patientDao.update(entity);
    }

    @Override
    public List<FileVo> listFile(PatientListFileForm form) {
        PatientEntity entity = this.getByIdMustExists(form.getId());
        if(StrUtil.equals(form.getType(),"studyCase")){
            return entity.getStudyCaseFile();
        }
        return entity.getInformedConsentFile();
    }

    @Override
    public File downloadSingle(PatientDownloadSingleFileForm form) {
        PatientEntity entity = this.getByIdMustExists(form.getId());
        List<FileVo> files = entity.getInformedConsentFile();
        if(StrUtil.equals(form.getType(),"studyCase")){
            files = entity.getStudyCaseFile();
        }

        Assert.isTrue(StrUtil.isNotEmpty(form.getFileName()),"请选择要下载文件");
        Assert.isTrue(CollUtil.isNotEmpty(files),"该患者没有上传文件");

        List<FileVo> collect = files.stream().filter(item -> StrUtil.equals(item.getName(), form.getFileName())).collect(Collectors.toList());
        Assert.isTrue(CollUtil.isNotEmpty(collect),"文件不见了");

        return cn.hutool.core.io.FileUtil.file(fileConfig.getSavePath()+collect.get(0).getPath());
    }

    @SneakyThrows
    @Override
    public File download(PatientDownloadFileForm form) {
        PatientEntity entity = this.getByIdMustExists(form.getId());
        List<FileVo> files = entity.getInformedConsentFile();
        if(StrUtil.equals(form.getType(),"studyCase")){
            files = entity.getStudyCaseFile();
        }
        Assert.isTrue(CollUtil.isNotEmpty(files), "没有文件，请先上传");

        // 把所有文件打成zip提供下载
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ZipOutputStream zip = new ZipOutputStream(outputStream);
        for (FileVo vo : files) {
            // 添加到zip
            File file = cn.hutool.core.io.FileUtil.file(fileConfig.getSavePath() + vo.getPath());
            zip.putNextEntry(new ZipEntry(vo.getName()));
            IoUtil.write(zip, false, cn.hutool.core.io.FileUtil.readBytes(file));
            zip.flush();
            zip.closeEntry();
        }
        IoUtil.close(zip);
        FileUtil.download(outputStream);
        return null;
    }

    private void fillData(Map<String, PatientEntity> patientMap, List<?> list) {
        if (CollUtil.isNotEmpty(list)) {
            list.stream().forEach(item -> {
                Object fieldValue = ReflectUtil.getFieldValue(item, "patientCode");
                PatientEntity entity = patientMap.get(fieldValue);
                ReflectUtil.setFieldValue(item, "hospitalSite", entity.getHospitalSite());
                ReflectUtil.setFieldValue(item, "patientName", entity.getPatientName());
                ReflectUtil.setFieldValue(item, "testItem", entity.getTestItem());
                ReflectUtil.setFieldValue(item, "belongQueue", entity.getBelongQueue());
            });
        }
    }

    public HorizontalCellStyleStrategy buildExcelStyle() {
        // 自定义样式
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        headWriteCellStyle.setBorderBottom(BorderStyle.THIN);
        headWriteCellStyle.setBorderLeft(BorderStyle.THIN);
        headWriteCellStyle.setBorderRight(BorderStyle.THIN);
        headWriteCellStyle.setBorderTop(BorderStyle.THIN);
        headWriteCellStyle.setFillForegroundColor(IndexedColors.PALE_BLUE.getIndex()); // 设置浅绿色背景
        headWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND); // 设置填充模式为实心
        headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);

        WriteFont headWriteFont = new WriteFont();
        headWriteFont.setFontHeightInPoints((short) 14);
        headWriteFont.setBold(true);
        headWriteFont.setFontName("宋体");
        headWriteCellStyle.setWriteFont(headWriteFont);

        WriteFont cellWriteFont = new WriteFont();
        cellWriteFont.setFontHeightInPoints((short) 14);
        headWriteFont.setFontName("宋体");
        WriteCellStyle cellStyle = new WriteCellStyle();
        cellStyle.setWrapped(true);
        cellStyle.setWriteFont(cellWriteFont);
        cellStyle.setBorderBottom(BorderStyle.THIN);
        cellStyle.setBorderLeft(BorderStyle.THIN);
        cellStyle.setBorderRight(BorderStyle.THIN);
        cellStyle.setBorderTop(BorderStyle.THIN);
        cellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);

        // 应用样式
        HorizontalCellStyleStrategy horizontalCellStyleStrategy =
                new HorizontalCellStyleStrategy(headWriteCellStyle, cellStyle);
        return horizontalCellStyleStrategy;
    }

    private PatientEntity getByIdMustExists(Long id) {
        Assert.isTrue(ObjUtil.isNotNull(id), "请选择数据");
        PatientEntity entity = this.getById(id);
        Assert.isTrue(ObjUtil.isNotNull(entity), "数据失效，请重新选择数据");
        return entity;
    }
}
